"""
移动端自动化工具类
提供基础的手机App操作功能
使用 uiautomator2 库控制安卓设备
"""

import time
import logging
from typing import Optional, List, Dict, Tuple, Any
import uiautomator2 as u2
from PIL import Image


class MobileDriver:
    """移动端驱动封装类"""

    def __init__(self, config: dict):
        self.config = config
        self.device: Optional[u2.Device] = None
        self.logger = self._setup_logger()

    def _setup_logger(self) -> logging.Logger:
        """设置日志记录器"""
        logger = logging.getLogger("MobileDriver")
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger

    def init_device(self) -> None:
        """初始化移动设备连接，优先连接真机"""
        try:
            device_id = self.config.get("mobile", {}).get("device_id", "auto")

            def is_real_device(info: dict) -> bool:
                product = info.get("productName", "").lower()
                # 常见模拟器标识
                emulator_keywords = [
                    "emulator",
                    "sdk",
                    "genymotion",
                    "android sdk built",
                    "virtual",
                ]
                # 常见真机品牌
                real_brands = [
                    "xiaomi",
                    "huawei",
                    "oppo",
                    "vivo",
                    "samsung",
                    "oneplus",
                    "meizu",
                    "honor",
                    "realme",
                    "zte",
                    "lenovo",
                    "motorola",
                    "google",
                    "asus",
                    "nubia",
                ]
                if any(k in product for k in emulator_keywords):
                    return False
                if any(b in product for b in real_brands):
                    return True
                # 其他情况：如果不是模拟器关键词且有IMEI/序列号等
                return not any(k in product for k in emulator_keywords)

            if device_id == "auto":
                # 尝试多种方式获取和连接设备
                device_list = []

                # 方式1：使用adb命令（如果可用）
                try:
                    import subprocess

                    result = subprocess.check_output(
                        ["adb", "devices"], encoding="utf-8", timeout=10
                    )
                    lines = result.strip().splitlines()
                    for line in lines[1:]:
                        if line.strip() and "device" in line:
                            device_id_str = line.split()[0]
                            device_list.append(device_id_str)
                    self.logger.info(f"通过adb获取设备列表: {device_list}")
                except Exception as e:
                    self.logger.warning(f"adb命令不可用，尝试直接连接设备: {e}")

                # 方式2：如果adb不可用，直接尝试连接默认设备
                device_connected = False
                if not device_list:
                    try:
                        self.device = u2.connect()
                        info = self.device.info
                        if is_real_device(info):
                            self.logger.info(
                                f"已连接到默认真机设备: {info.get('productName', '')}"
                            )
                        else:
                            self.logger.info(
                                f"已连接到默认设备（可能是模拟器）: {info.get('productName', '')}"
                            )
                        device_connected = True
                    except Exception as e:
                        self.logger.error(f"连接默认设备失败: {e}")

                # 方式3：如果获得设备列表，遍历选择真机
                if device_list and not device_connected:
                    real_device_connected = False
                    for d in device_list:
                        try:
                            dev = u2.connect(d)
                            info = dev.info
                            if is_real_device(info):
                                self.device = dev
                                self.logger.info(
                                    f"优先连接真机: {d} ({info.get('productName', '')})"
                                )
                                real_device_connected = True
                                device_connected = True
                                break
                        except Exception as e:
                            self.logger.warning(f"设备 {d} 连接失败: {e}")

                    # 如果没有真机，连接第一个设备
                    if not real_device_connected and device_list:
                        try:
                            self.device = u2.connect(device_list[0])
                            info = self.device.info
                            self.logger.info(
                                f"未检测到真机，已连接到设备: {device_list[0]} ({info.get('productName', '')})"
                            )
                            device_connected = True
                        except Exception as e:
                            self.logger.error(f"连接设备失败: {e}")

                # 检查是否成功连接设备
                if (
                    not device_connected
                    or not hasattr(self, "device")
                    or not self.device
                ):
                    raise RuntimeError(
                        "未检测到任何可用设备，请确保设备已连接并开启USB调试"
                    )
            else:
                # 连接指定设备
                self.device = u2.connect(device_id)
                info = self.device.info
                self.logger.info(
                    f"已连接到设备: {device_id} ({info.get('productName', '')})"
                )

            # 获取设备信息
            info = self.device.info
            self.logger.info(
                f"设备信息: {info.get('productName', 'Unknown')} - {info.get('version', 'Unknown')}"
            )

            # 设置等待超时时间
            self.device.implicitly_wait(
                self.config.get("mobile", {}).get("implicit_wait", 10)
            )

        except Exception as e:
            self.logger.error(f"设备连接失败: {e}")
            raise

    def start_app(self, package_name: str = None) -> bool:
        """启动App"""
        try:
            if package_name is None:
                package_name = self.config.get("mobile", {}).get(
                    "app_package", "cn.damai"
                )

            self.logger.info(f"正在启动App: {package_name}")
            self.device.app_start(package_name)
            time.sleep(3)  # 等待App启动
            return True
        except Exception as e:
            self.logger.error(f"启动App失败: {e}")
            return False

    def stop_app(self, package_name: str = None) -> bool:
        """停止App"""
        try:
            if package_name is None:
                package_name = self.config.get("mobile", {}).get(
                    "app_package", "cn.damai"
                )

            self.logger.info(f"正在停止App: {package_name}")
            self.device.app_stop(package_name)
            time.sleep(1)
            return True
        except Exception as e:
            self.logger.error(f"停止App失败: {e}")
            return False

    def find_element(self, **kwargs) -> Optional[u2.UiObject]:
        """查找单个元素"""
        try:
            element = self.device(**kwargs)
            if element.exists:
                return element
            else:
                self.logger.warning(f"元素未找到: {kwargs}")
                return None
        except Exception as e:
            self.logger.error(f"查找元素出错: {e}")
            return None

    def find_elements(self, **kwargs) -> List[u2.UiObject]:
        """查找多个元素"""
        try:
            elements = []
            selector = self.device(**kwargs)
            count = selector.count
            for i in range(count):
                elements.append(selector[i])
            return elements
        except Exception as e:
            self.logger.error(f"查找元素出错: {e}")
            return []

    def click_element(self, timeout: int = 10, **kwargs) -> bool:
        """点击元素"""
        try:
            element = self.device(**kwargs)
            if element.wait(timeout=timeout):
                element.click()
                time.sleep(0.5)
                return True
            else:
                self.logger.warning(f"元素不可点击: {kwargs}")
                return False
        except Exception as e:
            self.logger.error(f"点击元素出错: {e}")
            return False

    def input_text(self, text: str, **kwargs) -> bool:
        """输入文本"""
        try:
            element = self.device(**kwargs)
            if element.exists:
                element.clear_text()
                element.set_text(text)
                time.sleep(0.3)
                return True
            else:
                self.logger.warning(f"输入框未找到: {kwargs}")
                return False
        except Exception as e:
            self.logger.error(f"输入文本出错: {e}")
            return False

    def wait_for_element(self, timeout: int = 10, **kwargs) -> bool:
        """等待元素出现"""
        try:
            element = self.device(**kwargs)
            return element.wait(timeout=timeout)
        except Exception as e:
            self.logger.error(f"等待元素出错: {e}")
            return False

    def swipe(
        self, fx: float, fy: float, tx: float, ty: float, duration: float = 0.5
    ) -> None:
        """滑动屏幕"""
        try:
            self.device.swipe(fx, fy, tx, ty, duration)
            time.sleep(0.5)
        except Exception as e:
            self.logger.error(f"滑动出错: {e}")

    def scroll_to_element(self, **kwargs) -> bool:
        """滚动到指定元素"""
        try:
            element = self.device(**kwargs)
            if element.exists:
                return True

            # 尝试向下滚动查找元素
            for _ in range(5):
                self.swipe(0.5, 0.8, 0.5, 0.2)
                if element.exists:
                    return True

            # 尝试向上滚动查找元素
            for _ in range(5):
                self.swipe(0.5, 0.2, 0.5, 0.8)
                if element.exists:
                    return True

            return False
        except Exception as e:
            self.logger.error(f"滚动查找元素出错: {e}")
            return False

    def tap_coordinate(self, x: int, y: int) -> None:
        """点击坐标"""
        try:
            self.device.click(x, y)
            time.sleep(0.5)
        except Exception as e:
            self.logger.error(f"点击坐标出错: {e}")

    def get_text(self, **kwargs) -> str:
        """获取元素文本"""
        try:
            element = self.device(**kwargs)
            if element.exists:
                return element.get_text()
            return ""
        except Exception as e:
            self.logger.error(f"获取文本出错: {e}")
            return ""

    def screenshot(self, filename: str = None) -> str:
        """截图"""
        try:
            if filename is None:
                filename = f"screenshot_{int(time.time())}.png"

            self.device.screenshot(filename)
            self.logger.info(f"截图已保存: {filename}")
            return filename
        except Exception as e:
            self.logger.error(f"截图失败: {e}")
            return ""

    def press_key(self, key: str) -> None:
        """按键操作"""
        try:
            self.device.press(key)
            time.sleep(0.3)
        except Exception as e:
            self.logger.error(f"按键操作出错: {e}")

    def press_back(self) -> None:
        """按返回键"""
        self.press_key("back")

    def press_home(self) -> None:
        """按Home键"""
        self.press_key("home")

    def press_recent(self) -> None:
        """按最近应用键"""
        self.press_key("recent")

    def get_current_activity(self) -> str:
        """获取当前Activity"""
        try:
            return self.device.app_current().get("activity", "")
        except Exception as e:
            self.logger.error(f"获取当前Activity出错: {e}")
            return ""

    def wait_activity(self, activity: str, timeout: int = 10) -> bool:
        """等待指定Activity"""
        try:
            start_time = time.time()
            while time.time() - start_time < timeout:
                current_activity = self.get_current_activity()
                if activity in current_activity:
                    return True
                time.sleep(1)
            return False
        except Exception as e:
            self.logger.error(f"等待Activity出错: {e}")
            return False

    def is_app_running(self, package_name: str = None) -> bool:
        """检查App是否运行"""
        try:
            if package_name is None:
                package_name = self.config.get("mobile", {}).get(
                    "app_package", "cn.damai"
                )

            return self.device.app_current().get("package") == package_name
        except Exception as e:
            self.logger.error(f"检查App运行状态出错: {e}")
            return False

    def close_device(self) -> None:
        """关闭设备连接"""
        try:
            if self.device:
                self.logger.info("设备连接已断开")
                # uiautomator2不需要显式关闭连接
        except Exception as e:
            self.logger.error(f"关闭设备连接出错: {e}")
